package com.tieto.user.service;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import lombok.Getter;
import lombok.Setter;

import org.springframework.stereotype.Repository;

import com.tieto.user.dto.User;

@Repository
public class UserManagementJPA implements UserManagement {
	@Getter
	@Setter
	private EntityManager entityManager;
	// using autowired for entityManagerFactory causes a side effect, the
	// database is not wiped between the test cases.
	@Getter
	@Setter
	private EntityManagerFactory entityManagerFactory;

	@PostConstruct
	public void initialize() {
		entityManagerFactory = Persistence
				.createEntityManagerFactory("Hibernate");
		entityManager = entityManagerFactory.createEntityManager();
		save(new User("admin", "admin", "admin"));
	}

	@PreDestroy
	public void finalize() {
		entityManager.close();
	}

	@Override
	public void delete(Iterable<? extends User> arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void deleteAll() {
		Iterable<User> users = findAll();
		if (users != null) {
			for (User user : users) {
				delete(user);
			}
		}
	}

	@Override
	public boolean exists(String username) {
		return findOne(username) != null;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Iterable<User> findAll() {
		final List<User> users = entityManager.createQuery(
				"select user from User user").getResultList();
		return users;
	}

	@Override
	@SuppressWarnings("unchecked")
	public User findOne(String username) {
		final List<User> users = entityManager.createQuery(
				"select u from User u").getResultList();
		for (User user : users) {
			if (user.getUsername().equals(username)) {
				return user;
			}
		}
		return null;
	}

	@Override
	public Iterable<User> save(Iterable<? extends User> users) {
		List<User> savedUsers = new ArrayList<User>();
		for (User user : users) {
			savedUsers.add(save(user));
		}
		return savedUsers;
	}

	@Override
	public User save(User user) {
		try {
			entityManager.getTransaction().begin();
			if (exists(user.getUsername())) {
				entityManager.merge(user);
			} else {
				entityManager.persist(user);
			}
		} catch (RuntimeException e) {
			throw e;
		} finally {
			entityManager.getTransaction().commit();
		}
		return user;
	}

	@Override
	public long count() {
		return ((List<User>) findAll()).size();
	}

	@Override
	public void delete(String username) {
		try {
			entityManager.getTransaction().begin();
			User dbUser = findOne(username);
			entityManager.remove(dbUser);
		} catch (RuntimeException e) {
			throw e;
		} finally {
			entityManager.getTransaction().commit();
		}
	}

	@Override
	public void delete(User user) {
		try {
			entityManager.getTransaction().begin();
			entityManager.remove(user);
		} catch (RuntimeException e) {
			throw e;
		} finally {
			entityManager.getTransaction().commit();
		}
	}
}
